#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <sys/time.h>
#include <errno.h>
#include <fcntl.h>
//#include <io.h>
#include "sm_kapi.h"
#include "sm_trace.h"
#include "itc.h"

typedef struct
{
	int           m_evt;
	unsigned char m_trans;
	xmsg_t        m_xmsg;
}QUEUEITEM;

#define ITC_MAX_TIMER 64

typedef struct tag_ci_timer_t
{
    unsigned short 	m_timerId ;
    unsigned long 	m_maxVal;	//timeout value, in ms
    unsigned long 	m_curVal;	//current value, in ms
    unsigned char  	m_taskAid;
    unsigned long	m_param;
}itc_timer_t ;

static sm_sem_t 		s_semTimer;
static itc_timer_t      s_arTimer[ITC_MAX_TIMER] ;
static unsigned char   	s_timerCount ;
static unsigned char   	s_timerLoop = 1;

unsigned long	g_startTime;

/****************************************************************************
*
* Task / Queue functions
*
****************************************************************************/

int ITC_Init(unsigned char taskAid)
{
	int		i;

	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_Init() - [%s %ld]entry, taskAid=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			taskAid);

	//temp for linux
	for (i = 0; i < SM_MAX_TASK_COUNT; i++)
	{
		if (g_arTasks[i].m_taskAid == taskAid)
		{
			g_arTasks[i].m_taskId = SM_GetCurTaskId();
			SM_TRACE_INFO(TRMOD_ITC, "ITC_Init() - set taskId=0%ld for taskAid=%d\r\n",
						g_arTasks[i].m_taskId, taskAid);
			break;
		}
	}

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_Init() - [%s %ld]return true\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
    return TRUE ;
}


int ITC_End( void )
{
	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_End() - [%s %ld]entry\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_End() - [%s %ld]Free task id\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
	SM_FreeTaskId(SM_GetCurTaskId());

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_End() - [%s %ld]return true\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
    return TRUE ;
}


BOOL ITC_RecvXmsg(xmsg_t* pXmsg, unsigned short timeout)
{
	unsigned int	taskId;
	unsigned char	queueFill[SM_QUEUE_LEN];

	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_RecvXmsg() - [%s %ld]entry,timeout=%d,"
			"sndrcver=0x%02X,pXmsg=0x%08X\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			(timeout==(unsigned short)-1)?-1:timeout, pXmsg->m_sndrcver, pXmsg);

	memset(pXmsg, 0x00, sizeof(xmsg_t));

	taskId = SM_GetCurTaskId();
	if (!taskId)
	{
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_RecvXmsg() - [%s %ld]invalid taskid\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
		return FALSE;
	}

	memset(&queueFill, 0x00, sizeof(queueFill));
	if (!SM_ReceiveQueueByTaskid(taskId, &queueFill,
			(timeout == (unsigned short)-1) ? -1 : timeout))
	{
		SM_TRACE_INFO(TRMOD_ITC, "ITC_RecvXmsg() - [%s %ld]receive queue timeout\r\n",
					GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
		return TRUE;
	}

    memcpy (pXmsg, queueFill, sizeof (xmsg_t));

	SM_TRACE_NOTIFY(TRMOD_ITC, "ITC_RecvXmsg() - [%s %ld]Received XMSG,"
				"msg=%s(0x%02X),%s(%d)-->%s(%d)\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				XMSG_NAME(pXmsg->m_type),
				pXmsg->m_type,
				GETTASKNAME(pXmsg->m_sndrcver >> 4), pXmsg->m_sndrcver >> 4,
				GETTASKNAME(pXmsg->m_sndrcver & 0xf), pXmsg->m_sndrcver & 0xf);

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_RecvXmsg() - [%s %ld]return true\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
    return TRUE;
}


BOOL ITC_SendXmsg(const xmsg_t* pXmsg)
{
	unsigned char	sndrcver;
	unsigned int	taskId;
	unsigned char	queueFill[SM_QUEUE_LEN];

	SM_ASSERT(pXmsg);
	sndrcver = pXmsg->m_sndrcver;

	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_SendXmsg() - [%s %ld]entry,"
			"sndrcver=0x%02X,pXmsg=0x%08X\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			sndrcver,pXmsg);

	taskId = SM_GetTaskIdByAid(sndrcver&0x0F);
	if (!taskId)
	{
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_SendXmsg() - [%s %ld]invalid sndrcver=0x%02X\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				sndrcver);
		return FALSE;
	}

	SM_TRACE_NOTIFY(TRMOD_ITC, "ITC_SendXmsg() - [%s %ld]Send xmsg,"
				"type=%s(0x%02X),%s(%d)-->%s(%d)\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				XMSG_NAME(pXmsg->m_type),
				pXmsg->m_type,
				GETTASKNAME(sndrcver >> 4), sndrcver >> 4,
				GETTASKNAME(sndrcver & 0xf), sndrcver & 0xf);

	memset(queueFill, 0x00, sizeof(queueFill));
	memcpy(queueFill, pXmsg, sizeof(xmsg_t));
	if (!SM_SendQueueByTaskid(taskId, &queueFill))
	{
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_SendXmsg() - [%s %ld]send queue failed\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
		return FALSE;
	}

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_SendXmsg() - [%s %ld]return true\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
    return TRUE;
}


/****************************************************************************
*
* Memory functions
*
****************************************************************************/


void* ITC_DynAlloc(unsigned long size)
{
	void* ptr = NULL;

	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_DynAlloc() - [%s %ld]entry,size=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			size);

	if (size <= 0)
	{
		SM_TRACE_ERROR(TRMOD_ITC,"ITC_DynAlloc() - size=%ld is invalid\r\n", size);
		return NULL;
	}

    ptr = SM_Malloc(size);
	if (ptr == NULL)
	{
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_DynAlloc() - [%s %ld]alloc failed,size=%d\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				size);
		return NULL;
	}

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_DynAlloc() - [%s %ld]return true,ptr=0x%08X,size=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			ptr, size);
	return ptr;
}

void* ITC_DynReAlloc(void* ptr, unsigned long size)
{
	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_DynReAlloc() - [%s %ld]entry,ptr=0x%08X,size=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			ptr, size);

    ptr = SM_Realloc(ptr, size);
	if (ptr == NULL)
	{
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_DynReAlloc() - [%s %ld]realloc failed,size=%d\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				size);
		return NULL;
	}

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_DynReAlloc() - [%s %ld]return true,ptr=0x%08X,size=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			ptr, size);
	return ptr;
}


int ITC_DynFree(void* ptr)
{
	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_DynFree() - [%s %ld]entry,ptr=0x%08X\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			ptr);

	SM_Free(ptr);

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_DynFree() - [%s %ld]return ok\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
	return 0;
}



/****************************************************************************
*
* Timer functions
*
****************************************************************************/

int itc_timer_thread(void* param)
{
    int 			timerIndex;
    unsigned short	timerId;
    xmsg_t 			xmsg;
    const int		interval = 100; //ms

    SM_TRACE_CRITICAL(TRMOD_ITC, "itc_timer_thread() - [%s %ld]entry\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());

    ITC_Init(ITC_TIMER);

    SM_CreateSem(&s_semTimer, "sm_itc_timer", 1);

    memset( s_arTimer, 0, sizeof(itc_timer_t)*ITC_MAX_TIMER ) ;
    s_timerCount = 0 ;

    while(s_timerLoop)
    {
    	SM_TRACE_INFO(TRMOD_ITC, "itc_timer_thread() - sleep %d ms...\r\n", interval);
    	SM_Sleep(interval);

        SM_ObtainSem(&s_semTimer, -1);
        for(timerIndex=0; timerIndex<ITC_MAX_TIMER; timerIndex++)
        {
        	//SM_TRACE_INFO(TRMOD_ITC, "itc_timer_thread() - timerIndex=%d, maxval=%lu,curval=%lu\r\n",
        	//		timerIndex, s_arTimer[timerIndex].m_maxVal, s_arTimer[timerIndex].m_curVal);
            if(!s_arTimer[timerIndex].m_maxVal)
				continue;

           	s_arTimer[timerIndex].m_curVal += interval;
            if(s_arTimer[timerIndex].m_curVal < s_arTimer[timerIndex].m_maxVal)
				continue;
			s_arTimer[timerIndex].m_maxVal = 0;

			timerId = s_arTimer[timerIndex].m_timerId;
			if (timerId > TMID_TRPT_PEND_BASE && timerId <= TMID_TRPT_PEND_BASE + MAXTCID)
				xmsg.m_type = TP_TMPEND;
			else if (timerId > TMID_TRPT_POLL_BASE && timerId <= TMID_TRPT_POLL_BASE + MAXTCID)
				xmsg.m_type = TP_TMPOLL;
			else if (timerId >= TMID_SESS_PEND_BASE && timerId < (TMID_SESS_PEND_BASE + MAXSSNB ))
				xmsg.m_type = SS_TMPEND;
			else if (timerId >= TMID_DT_POLL_BASE && timerId < (TMID_DT_POLL_BASE+ MAX_DT_TIMER))
				xmsg.m_type = DT_TMPOLL;
			else if (timerId >= TMID_APP_PEND_BASE && timerId < (TMID_APP_PEND_BASE+ APP_TIMER_COUNT))
				xmsg.m_type = APP_TMPEND;
			else
			{
				SM_ASSERT(FALSE);
				continue;
			}

			xmsg.m_sndrcver = s_arTimer[timerIndex].m_taskAid;
			xmsg.m_bd.m_timer.m_param = s_arTimer[timerIndex].m_param;
			xmsg.m_bd.m_timer.m_timerId = timerId;
			SM_TRACE_NOTIFY(TRMOD_ITC, 
					"[%s %ld]itc_timer_thread() - timer out, timerId=0x%02X,timeout_ms=%ld\r\n",
					GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
					s_arTimer[timerIndex].m_timerId, s_arTimer[timerIndex].m_curVal);
			ITC_SendXmsg(&xmsg);
        }
        SM_ReleaseSem(&s_semTimer);
    }

	SM_DestroySem(&s_semTimer);

	SM_TRACE_CRITICAL(TRMOD_ITC, "itc_timer_thread() - [%s %ld]return ok\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
    return 0;
}

unsigned short ITC_SetTimerEx(unsigned short timerId, unsigned long timeout_ms, unsigned long param)
{
    int timerIndex;

	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_SetTimerEx() - [%s %ld]entry,timerId=0x%02X,timeout_ms=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			timerId, timeout_ms);

    SM_ObtainSem(&s_semTimer, -1);
    if( s_timerCount >= ITC_MAX_TIMER )
    {
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_SetTimerEx() - [%s %ld]too many timer: 0x%02X\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				s_timerCount);
    	SM_ReleaseSem(&s_semTimer);
    	return 0; //error
	}

    for( timerIndex=0; timerIndex<ITC_MAX_TIMER; timerIndex++ )
    {
        if( s_arTimer[timerIndex].m_timerId == timerId)
        {
        	break;
        }
    }

   	if (timerIndex >= ITC_MAX_TIMER)
   	{
	    for( timerIndex=0; timerIndex<ITC_MAX_TIMER; timerIndex++ )
	    {
	        if( s_arTimer[timerIndex].m_timerId == 0 )
	        {
	            s_arTimer[timerIndex].m_timerId = timerId;
	            s_arTimer[timerIndex].m_maxVal = 0;
	            s_arTimer[timerIndex].m_curVal = 0;
	            s_arTimer[timerIndex].m_param = 0;
	            break;
	        }
	   }
	}

	s_arTimer[timerIndex].m_curVal = 0;
	s_arTimer[timerIndex].m_maxVal = timeout_ms;
	s_arTimer[timerIndex].m_param = param;

	if (timerId > TMID_TRPT_PEND_BASE && timerId <= TMID_TRPT_PEND_BASE + MAXTCID) //tcid is base 1
		s_arTimer[timerIndex].m_taskAid = TRANS ;
	else if (timerId > TMID_TRPT_POLL_BASE && timerId <= TMID_TRPT_POLL_BASE + MAXTCID)
		s_arTimer[timerIndex].m_taskAid = TRANS ;
	else if( timerId >= TMID_SESS_PEND_BASE && timerId < (TMID_SESS_PEND_BASE + MAXSSNB ) )
		s_arTimer[timerIndex].m_taskAid = SESS ;
	else if (timerId >= TMID_DT_POLL_BASE && timerId < (TMID_DT_POLL_BASE+ MAX_DT_TIMER))
		s_arTimer[timerIndex].m_taskAid = ITC_DT ;
	else if (timerId >= TMID_APP_PEND_BASE && timerId < (TMID_APP_PEND_BASE+ APP_TIMER_COUNT))
		s_arTimer[timerIndex].m_taskAid = RM;
	else
	{
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_SetTimerEx() - [%s %ld]not support timerId: 0x%02X\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				timerId);
    	SM_ReleaseSem(&s_semTimer);
    	return 0; //error
	}

	s_timerCount++ ;

    SM_ReleaseSem(&s_semTimer);

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_SetTimerEx() - [%s %ld]return,timerId=0x%02X,"
			"timerValue=%d,param=%lu,timeCount=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			timerId,s_arTimer[timerIndex].m_maxVal, s_arTimer[timerIndex].m_param,
			s_timerCount);
    return timerId;
}


unsigned short ITC_SetTimer(unsigned short timerId, unsigned long timeout_ms)
{
	return ITC_SetTimerEx(timerId, timeout_ms, 0);
}


BOOL ITC_KillTimer(unsigned short timerId)
{
    int timerIndex;

	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_KillTimer() - [%s %ld]entry, timerId=%d\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
			timerId);

    SM_ObtainSem(&s_semTimer, -1);

    for (timerIndex=0; timerIndex < ITC_MAX_TIMER; timerIndex++)
    {
        if( s_arTimer[timerIndex].m_timerId == timerId)
        {
            memset(&s_arTimer[timerIndex], 0x00, sizeof(itc_timer_t)) ;
            s_timerCount-- ;
            break ;
        }
    }

    SM_ReleaseSem(&s_semTimer);

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_KillTimer() - [%s %ld]return true\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
    return TRUE ;
}


void ITC_ExitTimerThread(void)
{
	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_ExitTimerThread() - [%s %ld]entry\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());

    SM_ObtainSem(&s_semTimer, -1);
    s_timerLoop = 0;
    SM_ReleaseSem(&s_semTimer);

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_ExitTimerThread() - [%s %ld]return\r\n",
			GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId());
}


void ITC_Sleep(int delay_ms)
{
	SM_Sleep(delay_ms);
}


void FreeXmsg(xmsg_t* pXmsg) //add by pmy
{
	if (pXmsg == NULL)
		return;

	switch (pXmsg->m_type)
	{
	case LPDU:
		if (pXmsg->m_bd.m_lpdu.m_pbLpdu)
		{
			ITC_DynFree(pXmsg->m_bd.m_lpdu.m_pbLpdu);
			pXmsg->m_bd.m_lpdu.m_pbLpdu = NULL;
		}
		break;

	case TPDU:
		if (pXmsg->m_bd.m_tpdu.m_pbTpdu)
		{
			SM_TRACE_INFO(TRMOD_ITC, "[%s %ld]FreeXmsg() - free tpdu=0x%08X\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				pXmsg->m_bd.m_tpdu.m_pbTpdu);
			ITC_DynFree(pXmsg->m_bd.m_tpdu.m_pbTpdu);
			pXmsg->m_bd.m_tpdu.m_pbTpdu = NULL;
		}
		break;

	case SPDU:
		if (pXmsg->m_bd.m_spdu.m_pbSpdu)
		{
			SM_TRACE_INFO(TRMOD_ITC, "[%s %ld]FreeXmsg() - free spdu=0x%08X\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				pXmsg->m_bd.m_spdu.m_pbSpdu);
			ITC_DynFree(pXmsg->m_bd.m_spdu.m_pbSpdu);
			pXmsg->m_bd.m_spdu.m_pbSpdu = NULL;
		}
		break;

	case APDU:
		if (pXmsg->m_bd.m_apdu.m_pbApdu)
		{
			SM_TRACE_INFO(TRMOD_ITC, "[%s %ld]FreeXmsg() - free apdu=0x%08X\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				pXmsg->m_bd.m_apdu.m_pbApdu);
			ITC_DynFree(pXmsg->m_bd.m_apdu.m_pbApdu);
			pXmsg->m_bd.m_apdu.m_pbApdu = NULL;
		}
		break;

	case APP_APDU:
		if (pXmsg->m_bd.m_app_apdu.m_pbApdu)
		{
			SM_TRACE_INFO(TRMOD_ITC, "[%s %ld]FreeXmsg() - free app_apdu=0x%08X\r\n",
				GETTASKNAME(SM_GetTaskAid(SM_GetCurTaskId())), SM_GetCurTaskId(),
				pXmsg->m_bd.m_app_apdu.m_pbApdu);
			ITC_DynFree(pXmsg->m_bd.m_app_apdu.m_pbApdu);
			pXmsg->m_bd.m_app_apdu.m_pbApdu = NULL;
		}
		break;

	default:
		break;
	}
}


char* getxmsgname(unsigned int xmsgType)
{
	int	i;
	static unsigned char naName[30]="NA_MSG";
	static struct
	{
		unsigned char m_type;
		unsigned char m_name[30];
	}xmsgNames[] =
	{
		{PH_INSERT,"PH_INSERT"},
		{PH_DATA,"PH_DATA"},
		{PH_ERROR,"PH_ERROR"},
		{PH_EXTRACT,"PH_EXTRACT"},

		{LN_CONNECT,"LN_CONNECT"},
		{LN_DISCONNECT,"LN_DISCONNECT"},
		{LPDU,"LPDU"},
		{LN_ERROR,"LN_ERROR"},
		{LN_ACK,"LN_ACK"},

		{TP_CONNECT,"TP_CONNECT"},
		{TP_DISCONNECT,"TP_DISCONNECT"},
		{TPDU,"TPDU"},

		{SS_TC_CREATED,"SS_TC_CREATED"},
		{SS_DELETE_TC,"SS_DELETE_TC"},
		{SS_TC_DELETED,"SS_TC_DELETED"},
		{SPDU,"SPDU"},
		{RCVSPDU,"RCVSPDU"},

		{RM_TC_CREATED,"RM_TC_CREATED"},
		{RM_OPEN_SS_REQ,"RM_OPEN_SS_REQ"},
		{RM_OPEN_SS_RSP,"RM_OPEN_SS_RSP"},
		{RM_SS_OPENED,"RM_SS_OPENED"},
		{APDU,"APDU"},
		{RM_CLOSE_SS,"RM_CLOSE_SS"},
		{RM_SS_CLOSED,"RM_SS_CLOSED"},
		{RM_DELETE_TC,"RM_DELETE_TC"},
		{RM_TC_DELETED,"RM_TC_DELETED"},

		{t_sb,"t_sb"},
		{t_rcv,"t_rcv"},
		{create_t_c,"create_t_c"},
		{c_t_c_reply,"c_t_c_reply"},
		{delete_t_c,"delete_t_c"},
		{d_t_c_reply,"d_t_c_reply"},
		{request_t_c,"request_t_c"},
		{new_t_c,"new_t_c"},
		{t_c_error,"t_c_error"},
		{t_data_last,"t_data_last"},
		{t_poll,"t_poll"},
		{t_data_more,"t_data_more"},

		{dutag_open_session_request,"open_session_request"},
		{dutag_open_session_response,"open_session_response"},
		{dutag_create_session_request,"create_session"},
		{dutag_create_session_response,"create_session_response"},
		{dutag_close_session_request,"close_session_request"},
		{dutag_close_session_response,"close_session_response"},
		{dutag_session_number,"session_number"},

		{DT_TMPOLL,"dt_timer"},
		{TP_TMPEND,"tranout_timer"},
		{TP_TMPOLL,"tranpoll_timer"},
		{SS_TMPEND,"sessout_timer"},
		{XMG_EXIT,"XMG_EXIT"},
	};

	for (i = 0; i < countof(xmsgNames); i++)
	{
		if (xmsgNames[i].m_type == xmsgType)
			return xmsgNames[i].m_name;
	}

	return naName;
}


/****************************************************************************
*
* Specification of Abstract Syntax Notation One(ASN.1)
*
****************************************************************************/

unsigned char asnWriteLengthField(unsigned char* pbBuf, unsigned long dwLengthFieldValue)
{
	unsigned char	bBufLen;

	if (dwLengthFieldValue <= 0x7F)
	{
		if (pbBuf)
			pbBuf[0] = (unsigned char)dwLengthFieldValue;
		bBufLen = 1;
	}
	else if (dwLengthFieldValue <= 0xFF)
	{
		if (pbBuf)
		{
			pbBuf[0] = 1 | 0x80;
			pbBuf[1] = (unsigned char)dwLengthFieldValue;
		}
		bBufLen = 2;
	}
	else if (dwLengthFieldValue <= 0xFFFF)
	{
		if (pbBuf)
		{
			pbBuf[0] = 2 | 0x80;
			pbBuf[1] = (unsigned char)((dwLengthFieldValue >> 8) & 0xFF);
			pbBuf[2] = (unsigned char)dwLengthFieldValue;
		}
		bBufLen = 3;
	}
	else if (dwLengthFieldValue <= 0xFFFFFF)
	{
		if (pbBuf)
		{
			pbBuf[0] = 3 | 0x80;
			pbBuf[1] = (unsigned char)((dwLengthFieldValue >> 16) & 0xFF);
			pbBuf[2] = (unsigned char)((dwLengthFieldValue >> 8) & 0xFF);
			pbBuf[3] = (unsigned char)dwLengthFieldValue;
		}
		bBufLen = 4;
	}
	else
	{
		if (pbBuf)
		{
			pbBuf[0] = 4 | 0x80;
			pbBuf[1] = (unsigned char)((dwLengthFieldValue >> 24) & 0xFF);
			pbBuf[2] = (unsigned char)((dwLengthFieldValue >> 16) & 0xFF);
			pbBuf[3] = (unsigned char)((dwLengthFieldValue >> 8) & 0xFF);
			pbBuf[4] = (unsigned char)dwLengthFieldValue;
		}
		bBufLen = 5;
	}

	return bBufLen;
}


unsigned char asnReadLengthField(const unsigned char* pcbBuf, unsigned long dwBufSize,
						 unsigned long* pdwLengthFieldValue)
{
	unsigned char bLen;
	unsigned char i;

	if (pcbBuf[0] <= 0x7F)
	{
		if (pdwLengthFieldValue)
			*pdwLengthFieldValue = pcbBuf[0];
		bLen = 1;
	}
	else
	{
		bLen = (pcbBuf[0] & 0x7F) + 1;
		if (bLen <= dwBufSize)
		{
			if (pdwLengthFieldValue)
			{
				*pdwLengthFieldValue = 0;
				for (i = 1; i < bLen; i++)
					*pdwLengthFieldValue = (*pdwLengthFieldValue << 8) | pcbBuf[i];
			}
		}
		else
		{
			if (pdwLengthFieldValue)
				*pdwLengthFieldValue = 0;
			bLen = (unsigned char)dwBufSize;
		}
	}

	return bLen;
}



/****************************************************************************
*
* xpck functions
*
****************************************************************************/

static char* ITC_GetType(char type)
{
	char* pString;

	switch(type)
	{
	case XPCK_LPDU:
		pString = "PDU";
		break;
	case XPCK_CIS:
		pString = "CIS";
		break;
	case XPCK_SPY:
		pString = "SPY";
		break;
	default:
		pString = "   ";
		break;
	}
	return pString;
}

static char* ITC_GetDirection(char direction)
{
	char* pString;

	switch(direction)
	{
	case DIRECTION_M2H:
		pString = "H<-M";
		break;
	case DIRECTION_H2M:
		pString = "H->M";
		break;
	default:
		pString = "   ";
		break;
	}
	return pString;
}

BOOL ITC_SendXpck(int fd, char type, char direction, char *buf, short len)
{
	xpck_t			xpck;
	int				realSize;
	unsigned long	now;

	SM_TRACE_ENTRY(TRMOD_ITC, "ITC_SendXpck() - entry,fd=%d,type=%d,"
					"buf=0x%08X,len=%d\r\n", fd,type,buf,len);

 	if (len > sizeof(xpck.m_buf))
 	{
 		SM_TRACE_ERROR(TRMOD_ITC, "ITC_SendXpck() - invlaid len=%d\r\n", len);
 		return FALSE;
	}

	if(fd == -1)
	{
		SM_TRACE_ERROR(TRMOD_ITC, "ITC_SendXpck() - invlaid fd=-1\r\n");
		return FALSE;
	}

	memset(&xpck,0x00,sizeof(xpck));
	xpck.m_type = type;
	xpck.m_direction = direction;
	now = SM_OsMsecCountGet();
 	xpck.m_timestamp = now - g_startTime;
 	xpck.m_len = len;
 	memcpy(xpck.m_buf, buf, len);

	//SM_TRACE_BYTES(TRMOD_ITC, TRLEV_NOTIFY, (char*)&xpck, xpck.m_len+XPACK_HEAD_SIZE,"will send data:");
	//realSize = write(fd,&xpck,len+XPACK_HEAD_SIZE);
	//if(realSize != len+XPACK_HEAD_SIZE)
	//{
	//	SM_TRACE_ERROR(TRMOD_ITC, "ITC_SendXpck() - write to fifo failed,realSize=%d\n",realSize);
	//	return FALSE;
	//}
	{
		unsigned int	i;
		char			msg[80];
		time_t now;
		char buffer[40];

		time(&now);
		strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", localtime(&now));
		memset(msg, 0, sizeof(msg));
		sprintf(msg, "type:%s, direction:%s, time:%ld ms, data[%d]:", ITC_GetType(type), ITC_GetDirection(direction), xpck.m_timestamp, xpck.m_len);
		SM_TRACE_BYTES(TRMOD_ITC, TRLEV_NOTIFY, (char*)&xpck + XPACK_HEAD_SIZE, xpck.m_len,msg);
		realSize = write(fd, msg, strlen(msg));
		realSize += write(fd, "\r\n", 2);
		if(realSize != strlen(msg)+2)
		{
			SM_TRACE_ERROR(TRMOD_ITC, "ITC_SendXpck() - write to fifo failed,realSize=%d\n",realSize);
			return FALSE;
		}
		for(i=0; i<xpck.m_len; i++)
		{
			sprintf(msg, "0x%02x, ", (unsigned char)(*((char*)xpck.m_buf + i)));
			write(fd, msg, 6);
			if(i%16 == 15)
			{
				write(fd, "\r\n", 2);
			}
		}
		write(fd, "\r\n", 2);
	}

	SM_TRACE_RETURN(TRMOD_ITC, "ITC_SendXpck() - return true\n");
	return TRUE;
}


